/**
 * @author Cator Vee  hi@catorv.com
 */
import { isFunction } from '../utils'
import { ruid } from '../utils/guid'

const EXP_READY = /complete|loaded|interactive/
const EXP_CSS = /\.css$/i
const EXP_IMG = /(?:\.jpg|\.jpeg|\.png|\.gif)$/i

const body = document.body
let isReady = false

let promise = new Promise(function (resolve) {
  function onLoad (event) {
    if (event.type === 'load' || document.readyState === 'complete') {
      document.removeEventListener('DOMContentLoaded', onLoad, false)
      resolve()
    }
  }

  if (!isReady) {
    isReady = document.readyState === 'complete'
  }

  if (isReady) {
    resolve()
  } else {
    document.addEventListener('DOMContentLoaded', onLoad, false)
    window.addEventListener('load', onLoad, false)
  }
})

function load (url) {
  if (!url) {
    return Promise.resolve()
  }
  let name = url.replace(/\?.*$/, '')
  if (EXP_CSS.test(name)) {
    return loadCSS(url)
  } else if (EXP_IMG.test(name)) {
    return loadImage(url)
  }
  return loadJS(url)
}

export function loadImage (url, hack) {
  let iframe
  const Image = window.Image
  const name = ruid()
  const image = new Image()

  function clear () {
    if (name in Image) {
      delete Image[name]
    }
    if (iframe) {
      body.removeChild(iframe)
    }
  }

  if (hack) {
    Image[name] = '<img src="' + url + '">'
    iframe = document.createElement('iframe')
    // noinspection JSValidateTypes
    iframe.style = 'position:fixed;opacity:0;width:1px;height:1px'
    iframe.src = 'javascript:parent.Image.' + name
    body.appendChild(iframe)
  }

  image.src = url
  if (image.complete) {
    clear()
    return Promise.resolve(image)
  }
  return new Promise(function (resolve, reject) {
    image.onload = () => {
      clear()
      resolve(image)
    }
    image.onerror = event => {
      clear()
      reject(event)
    }
  })
}

export function loadCSS (url) {
  let el = document.createElement('link')
  el.rel = 'stylesheet'
  el.href = url
  body.appendChild(el)
  return Promise.resolve(url)
}

export function loadJS (url) {
  let el = document.createElement('script')
  el.src = url
  // el.charset = 'utf-8'
  // el.async = true
  body.appendChild(el)

  return new Promise(function (resolve, reject) {
    function detach (node) {
      node.removeEventListener('load', onLoad, false)
      node.removeEventListener('error', onError, false)
    }

    function onLoad (event) {
      if (event.type === 'load' || EXP_READY.test(el.readyState)) {
        detach(el)
        resolve(url)
      }
    }

    function onError () {
      detach(el)
      reject(url)
    }

    el.addEventListener('load', onLoad, false)
    el.addEventListener('error', onError, false)
  })
}

function pushPromise () {
  for (let i = 0; i < arguments.length; i++) {
    let item = arguments[i]
    promise = promise.then(isFunction(item) ? item : () => item)
  }
  return promise
}

export default function ready (fn) {
  if (isFunction(fn) || fn instanceof Promise) {
    return pushPromise(fn)
  }
  let args = arguments
  if (Array.isArray(args[0])) {
    args = args[0]
  }
  if (args.length > 0) {
    return Promise.all(Array.from(args, path => load(path)))
  }
}
